/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

import { describe, expect, test } from '@jest/globals';
import { copy } from 'fs-extra';
import { resolve } from 'path';

import { appRoot, initByStageEmptyApp, initByStageEmptyService, initExecuteCommand, runHvigor } from '../common/common';
import { ModuleBuildProfileModifier } from '../common/modifier/module-build-profile-modifier';
import { ModuleJsonModifier } from '../common/modifier/module-json-modifier';
import { ProjectBuildProfileModifier } from '../common/modifier/project-build-profile-modifier';

/**
 * api9-stage模型适配hos工程
 */
describe('Adapt Test', () => {
  test.concurrent('Hos api9 Stage runtimeOS', async () => {
    await initByStageEmptyApp({
      prepare: async (dir) => {
        await copy(resolve(appRoot(), 'test/resources/extra/target'), resolve(dir, 'entry/src/main'));
      },
      cb: async (dir) => {
        const moduleBuildProfileModifier = new ModuleBuildProfileModifier(dir, 'entry');
        moduleBuildProfileModifier.updateTarget({
          name: 'default',
          runtimeOS: 'HarmonyOS'
        }).outputSync();
        const projectBuildProfileModifier = new ProjectBuildProfileModifier(dir);
        projectBuildProfileModifier.setCompatibleSdkVersion(9);
        projectBuildProfileModifier.setSdkVersion(9);
        const moduleJsonModifier = new ModuleJsonModifier(dir, 'entry');
        moduleJsonModifier.setDeviceType(['default']).setExtensionAbilities([]).outputSync();

        const commands = initExecuteCommand({
          mode: 'module',
          product: 'default',
          module: 'entry@default',
          tasks: 'assembleHap'
        });

        // api9-stage模型deviceType 设备phone默认为default 此时schema校验报错
        try {
          runHvigor(dir, commands, { stderr: 'pipe' });
        } catch (e: any) {
          expect(e.stderr.includes('Schema validate failed'));
        }

        // 修改deviceType default为phone 校验通过 打包成功
        projectBuildProfileModifier.updateProduct({
          'name': 'default',
          'signingConfig': 'hos',
        }).outputSync();
        moduleJsonModifier.setDeviceType(['phone', 'tablet']).outputSync();
        const resultPhone = runHvigor(dir, commands);
        expect(resultPhone.stdout.includes('BUILD SUCCESSFUL')).toBeTruthy();

        // 无修改 PreBuild任务增量生效
        const resultForIncremental = runHvigor(dir, commands);
        expect(resultForIncremental.stdout).toContain('UP-TO-DATE :entry:default@PreBuild...');
        expect(resultForIncremental.stdout).toContain('BUILD SUCCESSFUL');
      }
    });
  });

  test.concurrent('HOS API9 API COMPATIBLE', async () => {
    await initByStageEmptyApp({
      cb: async (dir) => {
        const moduleBuildProfileModifier = new ModuleBuildProfileModifier(dir, 'entry');
        moduleBuildProfileModifier.updateTarget({
          name: 'default',
          runtimeOS: 'HarmonyOS'
        }).outputSync();
        const moduleJsonModifier = new ModuleJsonModifier(dir, 'entry');
        moduleJsonModifier.setExtensionAbilities([]).outputSync();

        const projectBuildProfileModifier = new ProjectBuildProfileModifier(dir);
        projectBuildProfileModifier.setCompatibleSdkVersion(8);
        projectBuildProfileModifier.setSdkVersion(9);
        projectBuildProfileModifier.outputSync();

        // hos-api9-stage模型设置compatibleSdkVersion为8, 与compileSdkVersion为9不兼容
        const commands = initExecuteCommand({
          mode: 'module',
          product: 'default',
          module: 'entry@default',
          tasks: 'assembleHap'
        });

        try {
          runHvigor(dir, commands, { stderr: 'pipe' });
        } catch (e: any) {
          const msg = 'According to the compatibility specifications, ' +
            'stage-model project can only support the development of API version 9 or later.';
          expect(e.stderr).toContain(msg);
        }

        const projectBuildProfileModifier2 = new ProjectBuildProfileModifier(dir);
        projectBuildProfileModifier2.setCompatibleSdkVersion(4);
        projectBuildProfileModifier2.setSdkVersion(9);
        projectBuildProfileModifier2.outputSync();

        try {
          runHvigor(dir, commands, { stderr: 'pipe' });
        } catch (e: any) {
          const msg = 'According to the compatibility specifications, ' +
            'apps of API version 9 or stage mode can only run on devices of API version 9 or later.';
          expect(e.stderr).toContain(msg);
        }
      }
    });
  });
});

describe('API9 Atomic service Test', () => {
  test.concurrent('stage service with HarmonyOs target', async () => {
    await initByStageEmptyService(async (projectRoot) => {
      const commands = initExecuteCommand({
        mode: 'module',
        product: 'default',
        module: 'entry@default',
        tasks: 'default@PreBuild'
      });
      new ModuleJsonModifier(projectRoot, 'entry').setDeviceType(['phone', 'tablet']).outputSync();
      new ModuleBuildProfileModifier(projectRoot, 'entry').updateTargetRuntimeOS('default', 'OpenHarmony');
      new ModuleBuildProfileModifier(projectRoot, 'feature').updateTargetRuntimeOS('default', 'OpenHarmony');
      new ModuleBuildProfileModifier(projectRoot, 'slibrary').updateTargetRuntimeOS('default', 'OpenHarmony');
      const result = runHvigor(projectRoot, commands);
      expect(result.stderr.includes('Atomic service development is not supported in the OpenHarmony stage model.'))
        .toBeTruthy();
      new ModuleBuildProfileModifier(projectRoot, 'entry').updateTargetRuntimeOS('default', 'HarmonyOS');
      new ModuleBuildProfileModifier(projectRoot, 'feature').updateTargetRuntimeOS('default', 'HarmonyOS');
      new ModuleBuildProfileModifier(projectRoot, 'slibrary').updateTargetRuntimeOS('default', 'HarmonyOS');
      const newResult = runHvigor(projectRoot, commands);
      expect(newResult.stdout.includes('BUILD SUCCESS'))
        .toBeTruthy();
    });
  });

  test.concurrent('stage service with API 9', async () => {
    await initByStageEmptyService(async (projectRoot) => {
      const commands = initExecuteCommand({
        mode: 'module',
        product: 'default',
        module: 'entry@default',
        tasks: 'default@PreBuild'
      });
      new ModuleBuildProfileModifier(projectRoot, 'entry').updateTarget({
        name: 'default',
        runtimeOS: 'HarmonyOS'
      }).outputSync();
      new ModuleJsonModifier(projectRoot, 'entry').setDeviceType(['phone', 'tablet']).outputSync();

      const result = runHvigor(projectRoot, commands);
      expect(result.stdout.includes('BUILD SUCCESS')).toBeTruthy();
    });
  });

  test.concurrent('stage app with extensionAbilities', async () => {
    await initByStageEmptyApp(async (projectRoot) => {
      const commands = initExecuteCommand({
        mode: 'module',
        product: 'default',
        module: 'entry@default',
        tasks: 'default@PreBuild'
      });
      new ModuleBuildProfileModifier(projectRoot, 'entry').updateTarget({
        name: 'default',
        runtimeOS: 'HarmonyOS'
      }).outputSync();
      new ModuleJsonModifier(projectRoot, 'entry').setExtensionAbilities([
        {
          'name': 'FormAbility',
          'srcEntry': './ets/FormAbility/FormAbility.ts',
          'label': '$string:form_FormAbility_label',
          'description': '$string:form_FormAbility_desc',
          'type': 'form',
          'metadata': [
            {
              'name': 'ohos.extension.form',
              'resource': '$profile:form_config'
            }
          ]
        }
      ]).setDeviceType(['phone', 'tablet']).outputSync();
      const result = runHvigor(projectRoot, commands);
      expect(result.stdout.includes('BUILD SUCCESS')).toBeTruthy();
    });
  });
});
